package sbpme.designer.parts;

import java.util.EventObject;
import java.util.List;

import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.SnapToGrid;
import org.eclipse.gef.SnapToHelper;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CommandStackListener;
import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gef.requests.CreateRequest;

import sbpme.designer.command.ActivityChangeConstraintCommand;
import sbpme.designer.command.ActivityCreateCommand;
import sbpme.designer.model.Activity;
import sbpme.designer.model.ProcessDiagram;


public class ProcessDiagramPart extends AbstractPart {

	private CommandStackListener stackListener;
	
	public ProcessDiagramPart() {
		stackListener = new CommandStackListener() {
			public void commandStackChanged(EventObject event) {
				getFigure().getUpdateManager().performUpdate();
			}
		};
	}

	protected List getModelChildren() {
		return ((ProcessDiagram)getModel()).getActivities();
	}
	
	public void activate() {
		super.activate();
		getViewer().getEditDomain().getCommandStack().addCommandStackListener(stackListener);
	}

	protected void createEditPolicies() {
		installEditPolicy(EditPolicy.NODE_ROLE, null);
		installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, null);
		installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, null);
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
		installEditPolicy(EditPolicy.LAYOUT_ROLE, new XYLayoutEditPolicy() {
			
			@Override
			protected Command getCreateCommand(CreateRequest request) {
				ActivityCreateCommand createCommand = new ActivityCreateCommand();
				createCommand.setActivity((Activity)request.getNewObject());
				createCommand.setParent((ProcessDiagram)getHost().getModel());
				createCommand.setLocation(request.getLocation());
				createCommand.setLabel("create a node");
				return createCommand;
			}
			
			@Override
			protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
				ActivityChangeConstraintCommand locationCommand = new ActivityChangeConstraintCommand();
				locationCommand.setActivity((Activity)child.getModel());
				locationCommand.setNewConstraint((Rectangle)constraint);
				return locationCommand;
			}
			
			protected Command createAddCommand(EditPart arg0, Object arg1) {
				return null;
			}

			protected Command getDeleteDependantCommand(Request arg0) {
				return null;
			}
		});
	}

	protected IFigure createFigure() {
		FreeformLayer layer = new FreeformLayer();
		layer.setLayoutManager(new FreeformLayout());
		layer.setBorder(new LineBorder(1));
		return layer;
	}

	public void deactivate() {
		getViewer().getEditDomain().getCommandStack().removeCommandStackListener(stackListener);
		super.deactivate();
	}


	public boolean isSelectable() {
		return false;
	}

	protected void refreshVisuals() {
	}
	
	public Object getAdapter(Class adapter) {
		if (adapter == SnapToHelper.class) {
			return constructSnapToHelper();
		}
		return super.getAdapter(adapter);
	}

	private Object constructSnapToHelper() {
		Boolean val = (Boolean)getViewer().getProperty(SnapToGrid.PROPERTY_GRID_ENABLED);
		if (val != null && val.booleanValue()) {
			return new SnapToGrid(this);
		} else {
			return null;
		}		
	}

}
